#pragma once

using namespace Ogre;

#include "GameSession.h"
#include "Service.h"

class EventService;
class TaskService;
class RenderService;
class InputService;
class UIService;
class GameAppListener;

class Console;
class LogManagement;

class GameApp
{
public:
	virtual						~GameApp();

	static GameApp*				GetApp()					{ return m_App; }
	static GameApp*				createApp();
	
	GameAppListener*			GetAppListener()			{ return m_AppListener; }

	void						startApp();
	void						endApp();

public:
	//Root*						GetRoot()					{ return m_Root.getPointer(); }
	Root*						GetRoot()					{ return m_Root; }
	RenderWindow*				GetRenderWindow()			{ return m_Window; }
	Timer*						GetTimer()					{ return m_AppTimer; }
	LogManagement*				GetLog()					{ return m_LogManager; }

public:
	void						ResetServices();
	
	EventService*				GetEventService()			{ return m_EventService; }
	TaskService*				GetTaskService()			{ return m_TaskService; }
	RenderService*				GetRenderService()			{ return m_RenderService; }
	InputService*				GetInputService()			{ return m_InputService; }
	UIService*					GetUIService()				{ return m_UIService; }

private:
								GameApp();

	bool						InitApp();

	void						setupResource();
	void						loadResources();

private:
	void						InitServices();
	void						FinishServices();

	template<class TService>
	void						AddService(TService*& remember, TService* service)
								{ remember = service; m_Services.push_back(service); service->Reset(); }

	std::vector<Service*>		m_Services;

	EventService*				m_EventService;
	TaskService*				m_TaskService;
	RenderService*				m_RenderService;
	InputService*				m_InputService;
	UIService*					m_UIService;

public:
	GameSession*				GetActiveSession()								{ return m_ActiveSession; }

	void						SwitchTo(GameSession* session);
	void						Restart();
	
	void						StartSession();
	void						EndSession();
	void						ChangeActiveSession();

	GameSession*				m_ActiveSession;
	GameSession*				m_NextSession;

private:
	Root*						m_Root;
	RenderWindow*				m_Window;
	Ogre::String				m_ResourcePath;
	GameAppListener*			m_AppListener;
	Ogre::Timer*				m_AppTimer;

	LogManagement*				m_LogManager;

private:
	static GameApp*				m_App;
};

#define g_App			(GameApp::GetApp())
#define g_Session		((GameSession*)g_App->GetActiveSession())
#define g_Clock			((Timer*)g_App->GetTimer())
#define g_Log			((LogManagement*)g_App->GetLog())

#define g_EventService	((EventService*)g_App->GetEventService())
#define g_TaskService	((TaskService*)g_App->GetTaskService())
#define g_RenderService ((RenderService*)g_App->GetRenderService())
#define g_InputService	((InputService*)g_App->GetInputService())
#define g_UIService		((UIService*)g_App->GetUIService())
